home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / t_unix / j109lxa4.tar / forward.c < prev    next >
C/C++ Source or Header  |  1994-06-04  |  35KB  |  1,259 lines

  1. /* Some of the code in this file was originally based on the following file:
  2.  * gateway.c : Paul Healy, EI9GL, 900818
  3.  *
  4.  * Rewrote forwarding mechanism to use "X-Forwarded-To" paradigm instead of
  5.  * "X-BBS-To", added timer support, etc.  Anders Klemets, SM0RGV, 901009.
  6.  */
  7.  /* Mods by G1EMM and WG7J */
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <ctype.h>
  11. #include <time.h>
  12. #include "global.h"
  13. #include "config.h"
  14. #include "bm.h"
  15. #include "mailbox.h"
  16. #include "smtp.h"
  17. #include "cmdparse.h"
  18. #include "proc.h"
  19. #include "socket.h"
  20. #include "timer.h"
  21. #include "usock.h"
  22. #include "netuser.h"
  23. #include "ax25.h"
  24. #include "netrom.h"
  25. #include "nr4.h"
  26. #include "files.h"
  27.  
  28. #ifdef MBFWD
  29.  
  30. extern int MbForwarded;
  31. extern char MboxId[];
  32. #define ISPROMPT(s) (strlen(s) > 1 && s[strlen(s)-2] == '>')
  33. static struct timer fwdtimer;
  34. static struct proc *FwdProc = NULLPROC;
  35. static char bid[LINELEN];
  36.  
  37. static char *findident __ARGS((char *str, int n, char *result));
  38. static void sendmsg __ARGS((struct mbx *m,int msgn));
  39. static char *mbxtime __ARGS((char *line));
  40. static int fwdinit __ARGS((struct mbx *m));
  41. static char *fwdanybbs __ARGS((struct mbx *m,int *poll));
  42. static int timeok __ARGS((char *line));
  43. static void fwdtick __ARGS((void *v));
  44. static void fwdproc __ARGS((void));
  45. static int isconnbbs __ARGS((struct mbx *m));
  46. static void startfwd __ARGS((int a,void *v1,void *v2));
  47. static int openconn __ARGS((int argc,char *argv[],void *p));
  48. static int sendmsgtobbs __ARGS((struct mbx *m,int msgn,char *dest,int bulletin));
  49. static int makecl __ARGS((struct mbx *m,int msgn,char *dest,char *line,char *subj,int *bul));
  50. static char *grabtext __ARGS((char *from,char *to,int marker));
  51.  
  52. /***************************************************************************
  53.    findident copies the 'n'th alphanumeric sequence from 'str' to result.
  54.    It returns a ptr to result. It returns "\0" for missing identifier etc.
  55.    Uses isalnum macro to decide on alphanumeric/non-alnum status.
  56. */
  57. static char *
  58. findident(str, n, result)
  59. char *str, *result;
  60. int n;
  61. {
  62.    int count; /* current identifier */
  63.    count = 0;
  64.    *result = '\0';
  65.    while ( (count<n) && (*str!='\0') ) { /* Process alnum or non alnum seq */
  66.       while ( (*str!='\0') && (!isalnum(*str)) ) /* Get rid of ';:.@%"# etc */
  67.      str++;
  68.       if ( (*str!='\0') && isalnum(*str) ) { /* this is an alnum seq */
  69.      count++;
  70.      while ( (*str!='\0') && (isalnum(*str) || (*str=='_')) )
  71.         if (count==n)
  72.            *result++ = *str++;
  73.         else str++;
  74.      if (count==n)
  75.         *result = '\0';
  76.      }
  77.       }
  78.    return result;
  79. }
  80. /**************************************************************************/
  81. /* sendmsg() modified to send the R: line always.
  82.  * also added some additional strings like qth and zipcode etc. to R: line.
  83.  * Original SMTP headers get forwarded optionally.
  84.  * 920114 - WG7J
  85.  */
  86. extern char *Mbhaddress;
  87. extern char *Mbfwdinfo;
  88. extern char *Mbqth;
  89. extern char *Mbzip;
  90. extern int Mbsmtptoo;
  91. extern int UtcOffset;
  92. extern int Mbheader;
  93. extern char shortversion[];
  94.  
  95. static void
  96. sendmsg(m,msgn)
  97. struct mbx *m;
  98. int msgn;
  99. {
  100.     char buf[LINELEN], tb[LINELEN], *cp;
  101.     int len,rec = 0; /* rec is line-counter */
  102.     long cnt;
  103.     unsigned int msgid=0; /* message id number - WG7J */
  104.  
  105.     /*point to start of this message in file*/
  106.     fseek(m->mfile,m->mbox[msgn].start,0);
  107.     /*get message size*/
  108.     cnt = m->mbox[msgn].size;
  109.  
  110.     /* If the data part of the message starts with "R:" the RFC-822
  111.      * headers will not be forwarded. Instead we will add an R:
  112.      * line of our own.
  113.      */
  114.     /* ALWAYS forward with "R:" line - WG7J */
  115.     /* Now conditional upon Mbheader - 921201, WG7J */
  116.     if(Mbheader) {
  117.     for(;;) {
  118.         /*read a line*/
  119.         if(fgets(buf,sizeof(buf),m->mfile) == NULLCHAR)
  120.         break;
  121.         /*adjust message character count*/
  122.         cnt -= strlen(buf);
  123.         if(rec == 1) {
  124.         /* look at the line following Received:
  125.          * This has the ID followed by ' ; date&time in arpa-format'
  126.          */
  127.         /*get the message number from the ID line - WG7J*/
  128.         if((cp=strstr(buf,"AA"))!= NULLCHAR)
  129.             /*what follows is the message-number*/
  130.             msgid = atoi(cp+2);
  131.         /*get the ARPA format date/time string*/
  132.         if((cp = strchr(buf,';')) != NULLCHAR){
  133.             strcpy(tb,cp+1); /* point to the date of receipt */
  134.         }
  135.         /*If all of these are not set, don't send complete R: line*/
  136.         /* First send recv. date/time and bbs address */
  137.         usprintf(m->user,"R:%s",mbxtime(tb));
  138.         /* If exists, send H-address */
  139.         if(Mbhaddress != NULLCHAR)
  140.             usprintf(m->user," @:%s",Mbhaddress);
  141.         /* location, if any */
  142.         if(Mbqth != NULLCHAR)
  143.             usprintf(m->user," [%s]",Mbqth);
  144.         /*if there is info, put it next */
  145.         if(Mbfwdinfo != NULLCHAR)
  146.             usprintf(m->user," %s",Mbfwdinfo);
  147.         /* number of the message */
  148.         usprintf(m->user," #:%u",msgid);
  149.         /* The BID, is any */
  150.         if(strlen(bid) > 1)
  151.             usprintf(m->user," $:%s",&bid[1]);
  152.         /* zip code of the bbs */
  153.         if(Mbzip != NULLCHAR)
  154.             usprintf(m->user," Z:%s",Mbzip);
  155.         usputc(m->user,'\n');
  156.         break;
  157.         }
  158.         /* The first Received: line is the one that we have added */
  159.         if(!rec && htype(buf) == RECEIVED)
  160.         ++rec;
  161.     }
  162.     }
  163.  
  164.     /*Go past the SMTP headers to the data of the message.
  165.      *Check if we need to forward the SMTP headers!
  166.      *920114 - WG7J
  167.      */
  168.     for(;;) {
  169.     if(fgets(buf,sizeof(buf),m->mfile) == NULLCHAR)
  170.         break;
  171.     cnt -= strlen(buf);
  172.     if(*buf == '\n')    /* last header line */
  173.         break;
  174.     if(Mbsmtptoo) { /*YES, forward SMTP headers TOO !*/
  175.         switch(htype(buf)) {
  176.         case XFORWARD: /* Do not forward the "X-Forwarded-To:" lines */
  177.         case STATUS:   /* Don't forward the "Status:" line either */
  178.         case BBSTYPE:
  179.         case SUBJECT:
  180.         case TO:
  181.         case DATE:
  182.         break;
  183.         case FROM:
  184.         /* Don't forward the "From: " line either.
  185.          * make it ">From: "
  186.          */
  187.         cp = strdup(buf);
  188.         strcpy(buf,">");
  189.         strcat(buf,cp);
  190.         free(cp);        /*note fall-through*/
  191.         default:
  192.         usputs(m->user,buf);
  193.         }
  194.     }
  195.     }
  196.     /* If this is a message that originated locally,
  197.      * there are NO other R: headers
  198.      * in that case send a '\n',
  199.      * to separate the text from our R:-header - WG7J
  200.      */
  201.     if(fgets(buf,sizeof(buf),m->mfile) == NULLCHAR)
  202.     return; /* NO text ??? */
  203.     cnt -= strlen(buf);
  204.     if(strncmp(buf,"R:",2)) /* NO R: found! */
  205.     /*Now a blank line, separating our headers and body*/
  206.     usputc(m->user,'\n');
  207.     usputs(m->user,buf);
  208.  
  209.     /* the rest of the message is treated below */
  210.     do {
  211.         len = min(cnt,sizeof(buf)-1);
  212.         if(fread(buf,1,(size_t)len,m->mfile) != len)
  213.             break;
  214.         cnt -= len;
  215.         buf[len] = '\0';
  216.         usputs(m->user,buf);
  217.     } while(cnt);
  218. }
  219.  
  220. /* Parse a line for date and time in Arpanet format
  221.  * (Day, day Month year hh:mm:ss Zone) and return it in mailbox format
  222.  * (yymmdd/hhmmz)
  223.  */
  224. static char *
  225. mbxtime(line)
  226. char *line;
  227. {
  228.     extern char *Months[];
  229.     static char buf[13];
  230.     char *cp;
  231.     int year,month,day,hour,minute,maxdays;
  232.  
  233.     cp = line;
  234.     while(isspace(*cp))    /* skip initial blanks */
  235.     ++cp;
  236.     if(*cp == '\0')
  237.     return NULLCHAR;
  238.     if(strlen(cp) < 22)
  239.     return NULLCHAR;
  240.     cp += 5;
  241.     day = atoi(cp);
  242.     if(*(++cp) != ' ')
  243.     ++cp;
  244.     ++cp;
  245.     for(month=0; month < 12; ++month)
  246.     if(strnicmp(Months[month],cp,3) == 0)
  247.         break;
  248.     if(month == 12)
  249.     return NULLCHAR;
  250.  
  251.     /* Get things, and adjust for GMT/UTC time - WG7J */
  252.     month++;
  253.     year = atoi(cp+4);
  254.     hour = atoi(cp + 7);
  255.     minute = atoi(cp + 10);
  256.  
  257.     if(UtcOffset != 0) {
  258.     hour -= UtcOffset;
  259.     /* See if we went past midnight */
  260.     if(hour > 23) {
  261.         hour -= 24;
  262.         ++day;
  263.         /*Check for next month*/
  264.         if(month == 2) { /*February, check leap-year*/
  265.         if((year%4) == 0)
  266.             maxdays = 29;
  267.         else
  268.             maxdays = 28;
  269.         } else {
  270.         if((month%2) == 0)
  271.             maxdays = 30;
  272.         else
  273.             maxdays = 31;
  274.         }
  275.         if(day > maxdays) { /*adjust month*/
  276.         day = 1;
  277.         if(++month == 13) { /*next year*/
  278.             month = 1;
  279.             year++;
  280.         }
  281.         }
  282.     } else
  283.         if(hour < 0) { /*previous day !*/
  284.         hour += 24;
  285.         if(--day == 0) { /*previous month*/
  286.             if(--month == 0) { /*previous year*/
  287.             year--;
  288.             month = 12;
  289.             }
  290.             if(month == 2) { /* February, check leap year */
  291.             if((year%4) == 0)
  292.                 day = 29;
  293.             else
  294.                 day = 28;
  295.             } else {
  296.             if((month%2) == 0)
  297.                 day = 30;
  298.             else
  299.                 day = 31;
  300.             }
  301.         }
  302.         }
  303.     }
  304.  
  305.     sprintf(buf,"%02d%02d%02d/%02d%02dz",year,month,day,hour,minute);
  306.     return buf;
  307. }
  308.      
  309. static char *
  310. grabtext(from, to, marker)
  311. char *from, *to;
  312. int marker;
  313. {
  314.    while (*from!=marker)
  315.       *to++ = *from++;
  316.    *to = '\0';
  317.    return from+1;
  318. }
  319.  
  320. /* Makes a command line and returns -1 if the message cannot be sent. */
  321. static int
  322. makecl(m, msgn, dest, line, subj, bul)
  323. struct mbx *m;
  324. int msgn;               /* Message number */
  325. char *dest;             /* Destination address to use instead of To: line */
  326. char *line, *subj;      /* Buffers to keep command line and subject */
  327. int *bul;       /* True if message is in public message area */
  328. {
  329.    int bulletin = *bul;
  330.    int foundbid = 0;
  331.    char to[LINELEN], atbbs[LINELEN], from[LINELEN],
  332.     buf[LINELEN], *cp;
  333.  
  334.    if(m->mfile == NULLFILE)
  335.     return -1;
  336.  
  337.    if(!bulletin && (m->mbox[msgn].status & BM_READ))
  338.     return -1;      /* the message was already read */
  339.    fseek(m->mfile,m->mbox[msgn].start,0);
  340.    *bid = *to = *atbbs = *from = '\0';
  341.    if(subj != NULLCHAR)
  342.     *subj = '\0';
  343.    m->stype = bulletin ? 'B' : 'P';     /* default to SB or SP */
  344.    while (fgets(buf,sizeof(buf),m->mfile)) {
  345.       if (buf[0] == '\n')
  346.      break; /* envelope finished */
  347.       switch (htype(buf)) {
  348.       case TO:
  349.         /* The following code tries to parse "To: " lines where the
  350.          * address looks like any of the following: "to@atbbs",
  351.          * "<to@atbbs>", "<to%atbbs@host>" and with possible spaces
  352.          * surrounding the '<>' characters.
  353.          */
  354.         if((cp = getaddress(buf,0)) == NULLCHAR)
  355.             break;
  356.         strcpy(to,cp);
  357.         if((cp = strchr(to,'%')) != NULLCHAR) { /* look for a '%' */
  358.             strcpy(atbbs,cp + 1);
  359.             *cp = '\0';    /* "to" ends at the '%' character */
  360.         }
  361.         else {      /* no '%' but maybe a '@'? */
  362.             if((cp = strchr(to,'@')) != NULLCHAR) {
  363.                 strcpy(atbbs,cp + 1);
  364.                 *cp = '\0';   /* "to" ends at the '@' character */
  365.             }
  366.         }
  367.         if(*atbbs != '\0')          /* either '%' or '@' found */
  368.          /* cut "atbbs" at the first '@' character */
  369.          for(cp = atbbs; *cp != '\0'; ++cp)
  370.               if(*cp == '@') {
  371.                *cp = '\0';
  372.                break;
  373.               }
  374.         /* "to" or "atbbs" should not be more than 6 characters (ALEN).
  375.          * If "to" is too long, it might simply be because the area name
  376.          * is longer than 6 characters, but it might also be because
  377.          * the address on the To: line is in an obscure format that we
  378.          * failed to parse (eg '!' character notation.)
  379.          */
  380.         if(strlen(to) > ALEN) {
  381.         /* Play safe and set "to" and "atbbs" to the area name */
  382.         strcpy(to,m->area);
  383.         strcpy(atbbs,m->area);
  384.         }
  385.         if(*atbbs == '\0')
  386.         strcpy(atbbs,to);
  387.         to[ALEN] = '\0';
  388.         /* Only if the BBS supports "hierarchical routing designators"
  389.          * is the atbbs field allowd to be longer than 6 characters and
  390.          * have dots in it.
  391.          */
  392.         if((m->sid & MBX_HIER_SID) == 0) {
  393.          atbbs[ALEN] = '\0';    /* 6 character limit */
  394.          if((cp = strchr(atbbs,'.')) != NULLCHAR)
  395.               *cp = '\0';       /* cut "atbbs" at first dot */
  396.         }
  397.         break;
  398.       case MSGID:
  399.         /* The following code distinguishes between three different types
  400.          * of Message-IDs: <abcde@callsign.bbs>, <abcde@otherhost.domain>,
  401.          * and <abcde@ourhost.domain>.
  402.          * The first type is converted to $abcde and the second to
  403.          * $abcde_host.domain. The last to $abcde_first-part-of-H-address.
  404.          * This preserves compability with BBSes.
  405.          */
  406.         if((cp = getname(buf)) == NULLCHAR)
  407.             break;
  408.         bid[0] = '$';
  409.         strcpy(&bid[1],cp);
  410.         /* Is there a @hostname part ? */
  411.         if((cp = strchr(bid,'@')) != NULLCHAR) {
  412.             if(stricmp(&bid[strlen(bid) - 4], ".bbs") == 0) {
  413.                 /*retain the bid given by user*/
  414.                 *cp = '\0';
  415.                 foundbid = 1; /* Indicate we found a 'real' bid - WG7J */
  416.             } else {
  417.                 *cp++ = '_';
  418.                 if(strcmp(cp,Hostname) == 0) {
  419.                     /* This is one of our messages!
  420.                      * Take the _host part from the H-address,
  421.                      * to form our bid - WG7J 930205
  422.                      */
  423.                     strcpy(cp,Mbhaddress);
  424.                 }
  425.                 /* This is now either $msg#@my_h-address, or $msg#_host.domain
  426.                  * make this BID style '$msg#_host'
  427.                  * ie. cut off after first period - WG7J
  428.                  */
  429.                 if((cp = strchr(cp,'.')) != NULLCHAR)
  430.                     *cp = '\0';
  431.             }
  432.         }
  433. #ifdef notdef
  434.          else  /* MSGID is not msg@host format !?!? */
  435.             bid[0] = '\0';
  436. #endif
  437.         bid[13] = '\0';     /* BIDs should be no longer than 13 bytes */
  438.         break;
  439.       case SUBJECT:
  440.         if(subj != NULLCHAR) {
  441.             (void) grabtext(buf+9, subj, '\n');
  442.             /* Make sure subject isn't empty - WG7J */
  443.             cp = subj;
  444.             while(*cp == ' ' || *cp == '\t')
  445.                 cp++;
  446.             if(*cp == '\0')
  447.                 strcpy(subj,"(none)");
  448.         }
  449.         break;
  450.       case FROM:
  451.         if((cp = getaddress(buf,0)) != NULLCHAR) {
  452.             findident(cp, 1, from);         /* cp points to from@domain */
  453.             from[ALEN] = '\0';      /* 6 character limit */
  454.         }
  455.         break;
  456.       case XFORWARD:
  457.         if((cp = getaddress(buf,0)) == NULLCHAR)
  458.             break;
  459.         if(stricmp(m->name,cp) == 0)
  460.             /* This message has already been forwarded, abort */
  461.             return -1;
  462.         break;
  463.       case BBSTYPE:
  464.         m->stype = buf[16];
  465.     /* if it comes from a NTS area,
  466.      * always send as traffic, ie 'ST' - WG7J
  467.      */
  468.     if(!strnicmp(m->area,"nts",3))
  469.         m->stype = 'T';
  470.     if(m->stype == 'B') {
  471.         bulletin = 1;
  472.         *bul = 1;
  473.     }
  474.         break;
  475.       case XBBSHOLD:
  476.     /* This message is on hold. Do not forward ! - WG7J */
  477.     return -1;
  478.     
  479.       default:
  480.         break;
  481.       }
  482.    }
  483.    /* Check for an invalid RFC-822 header */
  484.    if((to[0] == '\0' && ((dest != NULLCHAR && *dest == '\0') ||
  485.       dest == NULLCHAR)) || from[0] == '\0')
  486.     return -1;
  487.  
  488.    if(line != NULLCHAR) {
  489.     if(dest != NULLCHAR && *dest != '\0'){
  490.          /* strip off hierarchical routing designators from the predefined
  491.           * destination address if they are not supported
  492.           */
  493.          if((m->sid & MBX_HIER_SID) == 0 && (cp = strchr(dest,'.')) !=
  494.            NULLCHAR)
  495.         *cp = '\0';
  496.          sprintf(line, "S%c %s < %s ", m->stype, dest, from);
  497.     }
  498.     else
  499.          sprintf(line, "S%c %s @ %s < %s ", m->stype, to, atbbs, from);
  500.     /* Add the bid to bulletins,
  501.      * AND ALSO to anything that came in with a bid !
  502.      * Takes care off duplicate 'SP SYSOP@xxx $BID' problems.
  503.      * ALSO add it to ALL messages if the remote system supports MID's - WG7J
  504.      */
  505.     if((m->sid & MBX_MID) || ((bulletin || foundbid) & (m->sid & MBX_SID)))
  506.          strcat(line,bid);
  507.     strcat(line,"\n");
  508.    }
  509.    return 0;
  510. }
  511.  
  512. static int /* 0 = ok, -1 = problem so disc */
  513. sendmsgtobbs(m, msgn, dest, bulletin)
  514. struct mbx *m;
  515. int msgn;
  516. char *dest;             /* Optional destination address to override To: line */
  517. int bulletin;
  518. {
  519.    int result = -1;
  520.    char line[64], subj[256];
  521.    if(makecl(m, msgn, dest, line, subj, &bulletin) == -1)
  522.     return 0;       /* do not forward this particular message */
  523.    tputs(line);          /* Send mail offer to bbs */
  524.    rip(line);
  525.    usflush(m->user);
  526.    if (recvline (m->user, m->line, MBXLINE) != -1 ) {
  527.       if (m->line[0] == 'O' || m->line[0] == 'o' || (m->sid & MBX_SID) == 0) {
  528.     /* Got 'OK' or any line if the bbs is unsofisticated */
  529.     tprintf("%s\n", subj);
  530.     sendmsg(m,msgn);   /* send the message */
  531.     tputs("/EX\n"); /* was 0x1a */
  532.     usflush(m->user);
  533.     /* get F> for a good deliver */
  534.     while (recvline (m->user, m->line, MBXLINE) != -1 )
  535.         if (ISPROMPT(m->line)) {
  536.             log(m->user,"MBOX bbs mail sent: %s ", line);
  537.             if(bulletin)
  538.                 m->mbox[msgn].status |= BM_FORWARDED;
  539.             else
  540.                 m->mbox[msgn].status |= BM_DELETE;
  541.             m->change = 1;
  542.             result = 0;
  543.         MbForwarded++;
  544.         break;
  545.         }
  546.       }
  547.       else { /* OK response not received from bbs */
  548.       if (m->line[0] == 'N' || m->line[0] == 'n') { /* 'NO' respone */
  549.         log(m->user,"MBOX bbs mail refused: %s\n     %s",line,m->line);
  550.         /* Mark refused message as forwarded if it is a bulletin.
  551.          * The message was probably a duplicate. Non-bulletin
  552.          * messages are sent without BID, so they cannot be dected
  553.          * as duplicates. The reason why it was refused is probably
  554.          * because the address was invalid. Retry later.
  555.      *
  556.      * After lots of complaining, this behaviour is changed:
  557.      * ALL messages that get the NO reply are marked
  558.      * as forwarded ! - WG7J 920124
  559.      */
  560.     /* if(bulletin){ */
  561.         m->mbox[msgn].status |= BM_FORWARDED;
  562.         m->change = 1;
  563.         /* Count this as forwarded ! - WG7J */
  564.         MbForwarded++;
  565.     /* } */
  566.       }
  567.       /* should get a F> here */
  568.       while (recvline (m->user, m->line, MBXLINE) != -1 )
  569.         if (ISPROMPT(m->line)) {
  570.             result = 0;
  571.             break;
  572.         }
  573.       }
  574.    } /* OK or NO here */
  575.    return result;
  576. }
  577.  
  578. /* This is the main entry point for reverse forwarding. It is also used
  579.  * for normal, "forward", forwarding.
  580.  */
  581. int
  582. dorevfwd(argc,argv,p)
  583. int argc;
  584. char *argv[];
  585. void *p;
  586. {
  587.     char oldarea[64], *cp;
  588.     struct mbx *m;
  589.     int i, bulletin, err = 0;
  590.  
  591.     m = (struct mbx *)p;
  592.     log(m->user,"MBOX forwarding mail to: %s ", m->name);
  593.     /* indicate we are doing reverse forwarding, if we are not already
  594.      * doing normal forwarding.
  595.      */
  596.     if(m->state != MBX_FORWARD)
  597.         m->state = MBX_REVFWD;
  598.     if(fwdinit(m) != -1) {
  599.         strcpy(oldarea,m->area);
  600.         while(!err && fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
  601.             if(*m->line == '-')     /* end of record reached */
  602.                 break;
  603.             rip(m->line);           /* adds extra null at end */
  604.             cp = strchr(m->line,' '); /* remove trailing blanks */
  605.             if(cp != NULLCHAR)
  606.                 *cp = '\0';
  607.             if((cp = strchr(m->line,'\t')) != NULLCHAR)
  608.                 *cp = '\0';
  609.             if(*m->line == '\0' || *m->line == '.')
  610.                 continue;
  611.             changearea(m,m->line);
  612.             bulletin = isarea(m->line);     /* public area */
  613.             /* get the optional destination field, cp will point
  614.              * at null byte if it is missing.
  615.              */
  616.             cp = &m->line[strlen(m->line)] + 1;
  617.             while(*cp != '\0' && isspace(*cp)) /* strip blanks */
  618.                  ++cp;
  619.             cp = strdup(cp);
  620.             for(i=1; i<=m->nmsgs; i++)
  621.                 if(sendmsgtobbs(m, i, cp, bulletin) == -1) {
  622.                     err = 1;        /* abort */
  623.                     break;
  624.                 }
  625.             free(cp);
  626.         }
  627.         fclose(m->tfile);
  628.         m->tfile = NULLFILE;
  629.         if(*oldarea != '\0')
  630.             changearea(m,oldarea);
  631.     }
  632.     if(m->state == MBX_FORWARD)
  633.         return 0;
  634.     tputs("*** Done\n");
  635. #ifdef notdef
  636.     /* Can't do this with polling anymore */
  637.     if((m->sid & MBX_RLI_SID))      /* disconnect if it is a W0RLI bbs */
  638.         return domboxbye(0,NULL,m);
  639. #endif
  640.     return 0;
  641. }
  642.  
  643. /* Read the forward file for a record for the connected BBS. If found,
  644.  * return 1 if this is the right time to forward, m->tfile is left pointing
  645.  * at the first message area to be forwarded.
  646.  */
  647. static int
  648. fwdinit(m)
  649. struct mbx *m;
  650. {
  651.     char host[80];
  652.     int start = 1;
  653.     if((m->tfile = fopen(Forwardfile,READ_TEXT)) == NULLFILE)
  654.         return -1;
  655.     while(fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
  656.         if(*m->line == '\n')
  657.             continue;
  658.         /* lines starting with '-' separate the forwarding records */
  659.         if(*m->line == '-') {
  660.             start = 1;
  661.             continue;
  662.         }
  663.         if(start) {
  664.             start = 0;
  665.             /* get the name of this forwarding record */
  666.             findident(m->line,1,host);
  667.             if(stricmp(m->name,host) == 0) {
  668.                 if(!timeok(m->line))
  669.                     break;
  670.                 /* eat the connect command line */
  671.                 fgets(m->line,MBXLINE,m->tfile);
  672.                 return 0;
  673.             }
  674.         }
  675.     }
  676.     fclose(m->tfile);
  677.     m->tfile = NULLFILE;
  678.     return -1;
  679. }
  680. /* Read the forward file for a record for the connected BBS. If found,
  681.  * determine if this is the right time to forward, and return the command
  682.  * line to establish a forwarding connection. m->tfile is left pointing
  683.  * at the first message area to be forwarded.
  684.  */
  685. static char *
  686. fwdanybbs(m,poll)
  687. struct mbx *m;
  688. int *poll;
  689. {
  690.     char host[80];
  691.     int start = 1,i;
  692.  
  693.     if(m->tfile == NULLFILE && (m->tfile = fopen(Forwardfile,READ_TEXT))
  694.                     == NULLFILE)
  695.         return NULLCHAR;
  696.     *poll = 0;  /* Default to no polling */
  697.     while(fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
  698.         if(*m->line == '\n')
  699.             continue;
  700.         /* lines starting with '-' separate the forwarding records */
  701.         if(*m->line == '-') {
  702.             start = 1;
  703.             continue;
  704.         }
  705.         if(start) {
  706.             start = 0;
  707.             /* get the name of this forwarding record */
  708.             findident(m->line,1,host);
  709.             strcpy(m->name,host);
  710.             if(!timeok(m->line))
  711.                 continue;       /* too late or too early */
  712.         /* Check for polling - WG7J */
  713.         i=2;
  714.         findident(m->line,2,host);
  715.         while(*host) {
  716.         if(*host == 'P' || *host == 'p') {
  717.             *poll = 1;
  718.             break;
  719.         }
  720.         i++;
  721.         findident(m->line,i,host);
  722.         }
  723.         /* get the connect command line */
  724.             fgets(m->line,MBXLINE,m->tfile);
  725.             return strdup(m->line);
  726.         }
  727.     }
  728.     fclose(m->tfile);
  729.     m->tfile = NULLFILE;
  730.     return NULLCHAR;
  731. }
  732.  
  733. /* get any groups of four digits that specify the begin and ending hours of
  734.  * forwarding. Returns 1 if forwarding may take place.
  735.  */
  736. static int
  737. timeok(line)
  738. char *line;
  739. {
  740.     char hours[80], *now;
  741.     long t;
  742.     int t1, t2, pos = 2;
  743.     findident(line,pos++,hours);
  744.     if(*hours == '\0' || *hours == 'P' || *hours == 'p')
  745.     return 1;       /* no digits default to 0023, ie. anytime */
  746.     time(&t);
  747.     now = ctime(&t) + 11;
  748.     *(now + 2) = '\0';
  749.     while(*hours != '\0') {
  750.         t1 = (*hours - '0') * 10 + (*(hours+1) - '0');
  751.         t2 = (*(hours+2) - '0') * 10 + (*(hours+3) - '0');
  752.         if(atoi(now) >= t1 && atoi(now) <= t2)
  753.             return 1;               /* right in time */
  754.         findident(line,pos++,hours);    /* get next group if any */
  755.     if(*hours == 'P' || *hours == 'p')
  756.         return 0;
  757.     }
  758.     return 0;       /* too early or too late */
  759. }
  760.  
  761. int
  762. dombtimer(argc,argv,p)
  763. int argc;
  764. char *argv[];
  765. void *p;
  766. {
  767.     if(argc < 2){
  768.     tprintf("Forwarding timer: %lu/%lu server %s.\n",
  769.         read_timer(&fwdtimer)/1000L,
  770.         dur_timer(&fwdtimer)/1000L,
  771.         FwdProc != NULLPROC ? "started":"stopped");
  772.         return 0;
  773.     }
  774.     fwdtimer.func = (void (*)__ARGS((void *)))fwdtick;/* what to call on timeout */
  775.     fwdtimer.arg = NULL;            /* dummy value */
  776.     set_timer(&fwdtimer,atol(argv[1])*1000L); /* set timer duration */
  777.     pwait(NULL);
  778.     if (FwdProc != NULLPROC)    /* if someone is listening */
  779.     start_timer(&fwdtimer);     /* fire it up */
  780.     else
  781.     if(dur_timer(&fwdtimer) != 0)
  782.         tputs("Warning: forward server not started.\n");
  783.     return 0;
  784. }
  785.  
  786. int
  787. dombkick(argc,argv,p)
  788. int argc;
  789. char *argv[];
  790. void *p;
  791. {
  792.     if (FwdProc == NULLPROC) {
  793.     tprintf("Forward server not started\n");
  794.     return 1;
  795.     }
  796.     psignal(&fwdtimer,0);
  797.     return 0;
  798. }
  799.  
  800. /* called when the forward timer expires or explicitly by dombkick() */
  801. /* MDMII: fwdproc is the old fwdtick.   But, since it can call pause, which is
  802.  * very very bad for timer functions :-( this has been converted to a server.
  803.  */
  804. static void
  805. fwdtick(v)
  806. void *v;
  807. {
  808.     psignal(&fwdtimer,0);           /* awake the forwarder */
  809.     start_timer(&fwdtimer);     /* and restart the timer */
  810. }
  811.  
  812. /* the main process for the mailbox forwarder */
  813. int
  814. #ifdef PROTOTYPES
  815. fwdstart(int argc,char **argv,void *p)
  816. #else
  817. fwdstart(argc,argv,p)
  818. int argc;
  819. char *argv[];
  820. void *p;
  821. #endif
  822. {
  823.   if (FwdProc != NULLPROC)
  824.       return 0;       /* already started */
  825.  
  826.   FwdProc = Curproc;      /* set our flag */
  827.  
  828.   psignal(Curproc,0);     /* don't wait on us */
  829.  
  830.   start_timer(&fwdtimer);     /* start timer (ignored if 0) */
  831.  
  832.   for (;!pwait(&fwdtimer);)   /* wait for someone to tell us to try */
  833. #ifndef UNIX
  834.       if (availmem() > Memthresh)
  835. #endif
  836.     fwdproc();
  837. #ifndef UNIX
  838.       else if(Mtrace)
  839.     tprintf("fwd: forwarding skipped due to low memory\n");
  840. #endif
  841.  
  842.   FwdProc = NULLPROC;     /* we are exiting */
  843.   return 0;           /* alerted from somewhere */
  844. }
  845.  
  846. /* (attempt to) kill the forwarder process */
  847. int
  848. #ifdef PROTOTYPES
  849. fwd0(int argc,char **argv,void *p)
  850. #else
  851. fwd0(argc,argv,p)
  852. int argc;
  853. char *argv[];
  854. void *p;
  855. #endif
  856. {
  857.   int i, max;         /* max attempts */
  858.  
  859.   stop_timer(&fwdtimer);      /* no more timer awakes */
  860.   max = 1;            /* Maximum attempts */
  861.   if (argc > 2)
  862.       setint(&max,NULLCHAR,argc,argv);
  863.  
  864.   for(i=0;i<max && FwdProc != NULLPROC;i++) {
  865.       alert(FwdProc,1);   /* signal regardless of location */
  866.       pwait(NULL);        /* let it see the alert */
  867.   }
  868.  
  869.   stop_timer(&fwdtimer);      /* in case timer tick restarted it */
  870.   return 0;
  871. }
  872.  
  873. /* MDMII: This is the old fwdtick function */
  874. static void
  875. fwdproc(void)
  876. {
  877.     char *cc, *cp;
  878.     struct mbx *m;
  879.     int i, bulletin, poll,skip = 0;
  880.  
  881.     if(Mtrace)
  882.     tputs("mbox: fwd started\n");
  883.     if((m = newmbx()) == NULLMBX){
  884.         if(Mtrace)
  885.         tputs("fwd: no new mbox\n");
  886.         return;
  887.     }
  888.     m->user = Curproc->output;
  889.     m->state = MBX_TRYING;
  890.     while((cc = fwdanybbs(m,&poll)) != NULLCHAR) {
  891.     if(isconnbbs(m)) { /* already connected to this BBS, skip it */
  892.             skip = 1;
  893.         if(Mtrace)
  894.         tprintf("fwd: %s already connected\n",m->name);
  895.     }
  896.     /* If we poll, there is no need to check message area, since this
  897.      * is also done later. It will speed things up here - WG7J
  898.      */
  899.     if(!skip && poll) {
  900.         if(Mtrace)
  901.         tprintf("fwd: polling %s\n",m->name);
  902.         newproc("Mbox forwarding", 2048,
  903.         startfwd, 0, (void *)cc,
  904.         (void *)strdup(m->name),0);
  905.         cc = NULLCHAR;
  906.         skip = 1;
  907.     }
  908.     if(!skip && Mtrace)
  909.         tprintf("fwd: %s - checking for messages\n",m->name);
  910.         while(fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
  911.             if(*m->line == '-') {   /* end of record reached */
  912.                 skip = 0;
  913.                 break;
  914.             }
  915.             if((cp = strchr(m->line,' ')) != NULLCHAR)
  916.                 *cp = '\0';
  917.             if((cp = strchr(m->line,'\t')) != NULLCHAR)
  918.                 *cp = '\0';
  919.         if(skip || *m->line == '\0' || *m->line == '.' || \
  920.         *m->line == '+' || *m->line == '@')
  921.                 continue;
  922.             rip(m->line);
  923.             changearea(m,m->line);
  924.             bulletin = isarea(m->line);     /* public area */
  925.             /* check if there are any messages in this area
  926.              * that need to be forwarded.
  927.              */
  928.             for(i=1; i<=m->nmsgs; i++)
  929.                 if(makecl(m, i, NULLCHAR, NULLCHAR, NULLCHAR,
  930.             &bulletin) == 0) {
  931.                     if(Mtrace)
  932.             tprintf("fwd: starting %s\n",m->name);
  933.                     newproc("Mbox forwarding", 2048,
  934.                         startfwd, 0, (void *)cc,
  935.                         (void *)strdup(m->name),0);
  936.                     skip = 1;
  937.                     cc = NULLCHAR;
  938.                     break;
  939.                 }
  940.         }
  941.         free(cc);
  942.     }
  943.     exitbbs(m);
  944. }
  945.  
  946. /* returns 1 if m->name matches the name of another connected mailbox. */
  947. static int
  948. isconnbbs(m)
  949. struct mbx *m;
  950. {
  951.     struct mbx *mp;
  952.  
  953.     for(mp=Mbox;mp;mp=mp->next)
  954.     if((stricmp(mp->name,m->name) == 0) &&
  955.        (m->state != MBX_TRYING) )
  956.         return 1;
  957.     return 0;
  958. }
  959.  
  960. /* possible commands on the command line in the forwarding file */
  961. static struct cmds cfwdcmds[] = {
  962.     "tcp",          openconn,       0, 0, NULLCHAR,
  963.     "telnet",       openconn,       0, 0, NULLCHAR,
  964. #ifdef AX25
  965.     "ax25",         openconn,       0, 0, NULLCHAR,
  966.     "connect",      openconn,       0, 0, NULLCHAR,
  967. #endif
  968. #ifdef NETROM
  969.     "netrom",       openconn,       0, 0, NULLCHAR,
  970. #endif
  971.     NULLCHAR
  972. };
  973.  
  974. /* this function is called whenever the forwarding timer expires */
  975. static void
  976. startfwd(a,v1,v2)
  977. int a;
  978. void *v1, *v2;
  979. {
  980.     struct mbx *m;
  981.     char *cc;
  982.     int32 timeout;
  983.     int rval;
  984.     char *cp;
  985.     char Continue[MBXLINE];
  986.  
  987.     cc = (char *) v1;
  988.     if((m = newmbx()) == NULLMBX) {
  989.         free(cc);
  990.         free((char *)v2);
  991.         return;
  992.     }
  993.     strcpy(m->name,(char *)v2);
  994.     free((char *)v2);
  995.     m->state = MBX_TRYING;
  996.     /* open the connection, m->user will be the new socket */
  997.     if(cmdparse(cfwdcmds,cc,(void *)m) == -1) {
  998.         free(cc);
  999.         exitbbs(m);
  1000.     /*            if(Mtrace)
  1001.             tputs("forward: unknown protocol\n");
  1002.     */            
  1003.         return;
  1004.     }
  1005.     free(cc);
  1006.     m->state = MBX_FORWARD;
  1007.     sockowner(m->user,Curproc);
  1008.     close_s(Curproc->output);
  1009.     close_s(Curproc->input);
  1010.     /* m->user will be closed automatically when this process exits */
  1011.     Curproc->output = Curproc->input = m->user;
  1012.     /* We'll do our own flushing right before we read input */
  1013.     setflush(m->user,-1);
  1014.  
  1015.     if(fwdinit(m) == -1) {
  1016.         /* it is probably not the right time to forward anymore */
  1017.         exitbbs(m);
  1018.         return;
  1019.     }
  1020.     /* read the connect script. Lines starting with a dot will be sent
  1021.      * to the remote BBS.
  1022.      */
  1023.     Continue[0] = '\0';
  1024.     while((cp=fgets(m->line,MBXLINE,m->tfile)) != NULLCHAR) {
  1025.     /* Expanded to do timeouts, and return string recognition - WG7J */
  1026.     if(*m->line == '.') {           /* send this line */
  1027.         tputs(m->line + 1);
  1028.         if(Mtrace)
  1029.         printf("fwd: %s > %s\n",m->name,m->line+1);
  1030.         Continue[0] = '\0';         /* reset reply string */
  1031.     } else if(*m->line == '+') {    /* string upon wich we continue ! */
  1032.         strcpy(Continue,m->line+1);
  1033.         rip(Continue);              /* get rid of \n */
  1034.     } else if(*m->line == '@') {    /* string that sets timeout */
  1035.         timeout = atoi(m->line+1);
  1036.         if(timeout)                 /* if a valid conversion */
  1037.         timeout *= 1000;        /* in ms ! */
  1038.         else
  1039.         timeout = 90*1000L;     /* default to 1.5 minutes */
  1040.         if(Mtrace)
  1041.         printf("fwd: %s, wait %ld < %s\n",m->name,timeout/1000,Continue);
  1042.         /* Now do the actual response interpretations */
  1043.         alarm(timeout);
  1044.         rval = recvline(m->user,m->line,MBXLINE);
  1045.         alarm(0L);
  1046.         /* Did we timeout, or connection disappear ? */
  1047.         if(Mtrace) {
  1048.         printf("fwd: %s, rx %d",m->name,rval);
  1049.         if(rval >= 0)
  1050.             printf(", %s",m->line);
  1051.         else
  1052.             putchar('\n');
  1053.         }
  1054.         if((rval < 0) || (strstr(m->line,Continue) == NULLCHAR)) {
  1055.         if(Mtrace)
  1056.             printf("fwd: %s, aborted!\n",m->name);
  1057.         exitbbs(m);
  1058.         return;
  1059.         }
  1060.         Continue[0] = '\0';         /* reset reply string */
  1061.     } else      /* must be the end of the script */
  1062.         goto go_on;
  1063.  
  1064.     usflush(m->user);   /* send it, if any */
  1065.     }
  1066.     /* Now we've past all in-between stuff, go talk to the bbs ! */
  1067. go_on:
  1068.     usflush(m->user);
  1069.     fclose(m->tfile);
  1070.     m->tfile = NULLFILE;
  1071.  
  1072.     /* make sure there is something left ! */
  1073.     if(cp == NULLCHAR) {
  1074.     if(Mtrace)
  1075.         puts("fwd: forward.bbs error!");
  1076.     exitbbs(m);
  1077.     return;
  1078.     }
  1079.     if(Mtrace)
  1080.     printf("fwd: %s, script done\n",m->name);
  1081.  
  1082.     /* read the initial output from the bbs, looking for the SID */
  1083.     for(;;) {
  1084.         if(recvline(m->user,m->line,MBXLINE) == -1) {
  1085.             exitbbs(m);
  1086.             return;
  1087.         }
  1088.         if(ISPROMPT(m->line))
  1089.             break;
  1090.         if(*m->line == '[') {           /* parse the SID */
  1091.         rip(m->line);
  1092.             mbx_parse(m);
  1093.             continue;
  1094.         }
  1095.     }
  1096.     /* Now sync the two ends as telnet password messes them up */
  1097.     if(socklen(m->user,0))          /* discard any remaining input */
  1098.         recv_mbuf(m->user,NULL,0,NULLCHAR,0);
  1099.  
  1100.     /* send our SID if the peer announced its SID */
  1101.     if(m->sid & MBX_SID) {
  1102.     tputs(MboxId);
  1103.         usflush(m->user);
  1104.         for(;;) {
  1105.             if(recvline(m->user,m->line,MBXLINE) == -1) {
  1106.                 exitbbs(m);
  1107.                 return;
  1108.             }
  1109.             if(ISPROMPT(m->line))
  1110.                 break;
  1111.         }
  1112.     }
  1113.     /* start the actual forwarding */
  1114.     dorevfwd(0,NULL,(void *)m);
  1115.     /* ask for reverse forwarding or just disconnect */
  1116.     if(((m->sid & MBX_SID) && tputs("F>\n") == -1) ||
  1117.        (m->sid & MBX_SID) == 0) {
  1118.         exitbbs(m);
  1119.         close_s(Curproc->output);
  1120.         return;
  1121.     }
  1122.     usflush(m->user);
  1123.     /* parse the commands that are are received during reverse
  1124.      * forwarding.
  1125.      */
  1126.     while(recvline(m->user,m->line,MBXLINE) > 0) {
  1127.         rip(m->line);
  1128.     if(mbx_parse(m) == -2)   /* got the "*** Done" command */
  1129.             break;
  1130.         tputs("F>\n");
  1131.         usflush(m->user);
  1132.     }
  1133.     exitbbs(m);
  1134.     close_s(Curproc->output);
  1135. }
  1136.  
  1137. /* open a network connection based upon information in the cc line.
  1138.  * m->user is set to the socket number.
  1139.  */
  1140. static int
  1141. openconn(argc,argv,p)
  1142. int argc;
  1143. char *argv[];
  1144. void *p;
  1145. {
  1146.     struct mbx *m;
  1147.     char sock[MAXSOCKSIZE], alias[AXBUF];
  1148.     struct nrroute_tab *rp;
  1149.     union sp sp;
  1150.     int len;
  1151.     char *remote;
  1152.  
  1153.     m = (struct mbx *)p;
  1154.     sp.p = sock;
  1155.     if(argc < 2) {
  1156.         if(Mtrace)
  1157.             tputs("fwd: connect command error\n");
  1158.         return -1;
  1159.     }
  1160.     remote = argv[1];
  1161.     switch(*argv[0]) {
  1162.     case 't':
  1163.         sp.in->sin_family = AF_INET;
  1164.         if((sp.in->sin_addr.s_addr = resolve(argv[1])) == 0) {
  1165.             if(Mtrace)
  1166.         tprintf("fwd: telnet - unknown host %s\n",argv[1]);
  1167.             return -1;
  1168.         }
  1169.         /* get the optional port number */
  1170.         if(argc > 2)
  1171.             sp.in->sin_port = atoip(argv[2]);
  1172.         else
  1173.             sp.in->sin_port = IPPORT_TELNET;
  1174.         if((m->user = socket(AF_INET,SOCK_STREAM,0)) == -1) {
  1175.             if(Mtrace)
  1176.                  tputs("fwd: unable to open telnet socket\n");
  1177.             return -1;
  1178.         }
  1179.         len = sizeof(*sp.in);
  1180.     m->family = AF_INET; /*So the user list will be correct! - WG7J */
  1181.     break;
  1182. #ifdef AX25
  1183.     case 'a':
  1184.     case 'c':       /* allow 'c' for 'connect' as well */
  1185.         if(argc < 3) {
  1186.             if(Mtrace)
  1187.                  tprintf("fwd: connect syntax error - %s %s ?\n",argv[0],argv[1]);
  1188.             return -1;
  1189.         }
  1190.         sp.ax->sax_family = AF_AX25;
  1191.         strncpy(sp.ax->iface,argv[1],ILEN); /* the interface name */
  1192.         setcall(sp.ax->ax25_addr,argv[2]); /* the remote callsign */
  1193.         /* no digipeaters for now, use the "ax25 route add" command */
  1194.         if((m->user = socket(AF_AX25,SOCK_STREAM,0)) == -1) {
  1195.             if(Mtrace)
  1196.                   tputs("fwd: Unable to open ax25 socket\n");
  1197.             return -1;
  1198.         }
  1199.         len = sizeof(*sp.ax);
  1200.     m->family = AF_AX25; /*So the user list will be correct! - WG7J */
  1201.     remote = argv[2];
  1202.     break;
  1203. #endif /* AX25 */
  1204. #ifdef NETROM
  1205.     case 'n':
  1206.     /* See if the requested destination could be an alias, and
  1207.      * use it if it is.  Otherwise assume it is an AX.25
  1208.      * address.
  1209.      */
  1210.     putalias(alias,argv[1],0);
  1211.     strupr(argv[1]);
  1212.     if ((rp = find_nrboth(alias,argv[1])) == NULLNRRTAB)  {
  1213.         if(Mtrace)
  1214.         tprintf("fwd: Netrom route unavailable - %s\n",argv[1]);
  1215.         return -1;
  1216.     }
  1217.     /* Setup the local side of the connection */
  1218.     sp.nr->nr_family = AF_NETROM;
  1219.         len = sizeof(*sp.nr);
  1220.         if((m->user = socket(AF_NETROM,SOCK_SEQPACKET,0)) == -1) {
  1221.              if(Mtrace)
  1222.               tprintf("fwd: unable to open netrom socket - %s\n",argv[1]);
  1223.             
  1224.              return -1;
  1225.         }
  1226.         memcpy(sp.nr->nr_addr.user,Nr4user,AXALEN);
  1227.     memcpy(sp.nr->nr_addr.node,Nr_iface->hwaddr,AXALEN);
  1228.         bind(m->user,sp.p,len);
  1229.  
  1230.     /* Now the remote side */
  1231.     memcpy(sp.nr->nr_addr.node,rp->call,AXALEN) ;
  1232.     /* The user callsign of the remote station is never
  1233.          * used by NET/ROM, but it is needed for the psocket() call.
  1234.          */
  1235.     memcpy(sp.nr->nr_addr.user,rp->call,AXALEN) ;
  1236.  
  1237.     m->family = AF_NETROM; /*So the user list will be correct! - WG7J */
  1238.     break;
  1239. #endif /* NETROM */
  1240.     default:
  1241.         if(Mtrace)
  1242.              tprintf("fwd: Invalid connect mode - %s\n",argv[0]);
  1243.         
  1244.         return -1;
  1245.     }
  1246.     sockmode(m->user,SOCK_ASCII);
  1247.     if(connect(m->user,sp.p,len) == -1) {
  1248.         log(m->user,"MBOX fwd failed: %s - %s errno %d",
  1249.         remote,sockerr(m->user),errno);
  1250.         if(Mtrace)
  1251.           tprintf("fwd: Connection failed to %s\n",remote);
  1252.         close_s(m->user);
  1253.         return -1;
  1254.     }
  1255.     return m->user;
  1256. }
  1257.  
  1258. #endif /*MBFWD*/
  1259.